package com.cjw.service.impl.database;

import cn.hutool.crypto.digest.MD5;
import cn.hutool.jwt.JWT;
import com.cjw.config.annotation.AutoFieldSuffer;
import com.cjw.enums.AutoFieldType;
import com.cjw.enums.ErrorCode;
import com.cjw.enums.user.UserState;
import com.cjw.enums.user.UserType;
import com.cjw.exceptions.BusinessException;
import com.cjw.mapper.database.OperationLogMapper;
import com.cjw.mapper.database.UserHasRoleMapper;
import com.cjw.mapper.database.UserMapper;
import com.cjw.pojo.dto.database.UserDTO;
import com.cjw.pojo.entity.database.OperationLog;
import com.cjw.pojo.entity.database.User;
import com.cjw.pojo.entity.database.UserHasRole;
import com.cjw.pojo.entity.person.UserDetail;
import com.cjw.pojo.query.database.RegisterUserDTO;
import com.cjw.service.database.ResourceService;
import com.cjw.service.database.RoleService;
import com.cjw.service.database.UserService;
import com.cjw.service.person.UserDetailService;
import com.cjw.util.AddressUtils;
import com.cjw.util.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private UserHasRoleMapper userHasRoleMapper;

    @Autowired
    private UserDetailService userDetailService;

    @Value("${jwt-key}")
    private String jwtKey;

    @Autowired
    OperationLogMapper logDao;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public UserDTO queryNormalById(Long id) {
        User user = userMapper.selectByPrimaryKey(id);
        if (user == null || user.getState() != UserState.NORMAL.getCode()) {
            throw new BusinessException(ErrorCode.USER_ID_NOT_FOUND);
        }
        return userToDTO(user);
    }

    @Override
    public String login(String username, String password) {
        User user1 = new User();
        user1.setPhone(username);
        User user = userMapper.selectOne(user1);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_OR_PASSWORD_INVALID);
        }
        String password2 = MD5.create().digestHex(password+user.getSalt());
        if (!user.getPassword().equals(password2)) {
            throw new BusinessException(ErrorCode.USER_OR_PASSWORD_INVALID);
        }

        String sign = JWT.create()
                .setPayload("phone", user.getPhone())
                .setPayload("username", user.getUserName())
                .setPayload("id", user.getId())
                .setKey(jwtKey.getBytes()).sign();
        saveOperLog(user, sign);
        return sign;
    }

    @Override
    @AutoFieldSuffer(AutoFieldType.ADD)
    @Transactional(rollbackFor = Exception.class)
    public String register(RegisterUserDTO registerUserDTO) {
        // 如果已经存在这个手机号，不能注册
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        if (userMapper.selectOneByExample(example) != null) {
            throw  new BusinessException(ErrorCode.PHONE_EXISTED);
        }

        User user = BeanUtils.copy(registerUserDTO, User.class);
        String salt = RandomStringUtils.randomAlphabetic(10);
        user.setSalt(salt);
        String s = MD5.create().digestHex(user.getPassword() + salt);
        user.setPassword(s);
        user.setType(UserType.USER.getCode());
        user.setState(UserState.NORMAL.getCode());

        // 为用户分配角色,这里默认是用户角色
        UserHasRole userHasRole = new UserHasRole();
        userHasRole.setUserId(user.getId());
        // 数据库user_role第一条数据为用户
        userHasRole.setRoleId(1L);

        UserDetail userDetail = new UserDetail();
        userDetail.setUserId(user.getId());
        return  (userMapper.insert(user) == 1 && userHasRoleMapper.insert(userHasRole) == 1
                && userDetailService.addUserDetail(userDetail))
            ? "注册成功" : "注册失败";
    }

    @Override
    public String getUserHeadUrl() {
        return userDetailService.getUserHeadUrl();
    }

    /**
     * 用户实体转换为用户DTO
     * @param user
     * @return
     */
    public UserDTO userToDTO(User user) {
        UserDTO userDTO = BeanUtils.copy(user, UserDTO.class);
        userDTO.setResourceDTOList(resourceService.queryByUserId(user.getId()));
        userDTO.setRoleDTOList(roleService.queryByUserId(user.getId()));
        return userDTO;
    }

    public void saveOperLog(User user, String result) {
        try {
            //将返回值转换成map集合
            OperationLog operationLog = new OperationLog();
            //获取操作
            operationLog.setModel("用户管理");
            operationLog.setType("GET");
            operationLog.setDescription("登录");
            //操作时间
            operationLog.setOperationTime(Timestamp.valueOf(sdf.format(new Date())));
            //操作用户
            operationLog.setUserCode(user.getId().toString());
            //操作IP
            AddressUtils addressUtils = new AddressUtils();
            operationLog.setIp(addressUtils.getInnetIp());
            //返回值信息
            operationLog.setResult(result);
            //保存日志
            logDao.insert(operationLog);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
